package com.zcy.gift.service.impl;

import com.zcy.constants.BaseConstants;
import com.zcy.domain.User;
import com.zcy.domain.UserInfo;
import com.zcy.dto.UserRegisterDTO;
import com.zcy.gift.client.AuthClient;
import com.zcy.gift.domain.LoginUser;
import com.zcy.gift.exception.BusinessException;
import com.zcy.gift.exception.ResponseCode;
import com.zcy.gift.exception.RonghuaAssert;
import com.zcy.gift.mapper.UserInfoMapper;
import com.zcy.gift.mapper.UserMapper;
import com.zcy.gift.service.IUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zcy.gift.util.AjaxResult;
import com.zcy.gift.util.StrUtils;
import com.zcy.gift.util.encrypt.MD5;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author zcy
 * @since 2024-01-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AuthClient authClient;

    @Override
    public void sendRegisterSmsByPhone(String phone) {
        // 参数校验
        RonghuaAssert.isNotBlank(phone, ResponseCode.RESPONSE_CODE_40027);
        // 判断手机号是否已注册
        User user = userMapper.loadByPhone(phone);
        RonghuaAssert.isNull(user, ResponseCode.RESPONSE_CODE_40030);
        // 从redis中获取验证码
        String redisSmsCode = getRedisSmsCode(BaseConstants.SEND_REGISTER_SMS_PREFIX + phone);

        // 6 发送短信
        String msg = "您正在进行用户注册,手机验证码为%s,请妥善保管.请在5分钟以内使用";
        msg = String.format(msg, redisSmsCode);
        // 发送短信
//        smsUtil.SendVerificationCode(dto.getPhone(), smsCode, registerSmsVerificationCode);
        System.out.println(msg);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void registerByPhone(UserRegisterDTO userRegisterDTO) {
        // 校验短信验证码是否正确
        String redisCode = (String) redisTemplate.opsForValue().get(BaseConstants.SEND_REGISTER_SMS_PREFIX + userRegisterDTO.getPhone());
        RonghuaAssert.isNotBlank(redisCode, ResponseCode.RESPONSE_CODE_40021);
        if (!userRegisterDTO.getSmsCode().equals(redisCode.split(":")[0])) {
            throw new BusinessException(ResponseCode.RESPONSE_CODE_40022);
        }

        String salt = UUID.randomUUID().toString();
        String password = getMD5Password(salt, userRegisterDTO.getPassword());


        LoginUser loginUser = new LoginUser().setUsername(UUID.randomUUID().toString().replaceAll("-", ""))
                .setPassword(password)
                .setSalt(salt)
                .setTel(userRegisterDTO.getPhone())
                .setType(BaseConstants.LoginInfo.TYPE_ADMIN);

        // 调用鉴权中心，保存登录信息
        AjaxResult ajaxResult = authClient.addOrUpdate(loginUser);
        loginUser.setId(Long.parseLong(ajaxResult.getResultObj().toString()));

        long createTime = new Date().getTime();
        User user = new User()
                .setCreateTime(createTime)
                .setUpdateTime(createTime)
                .setPassword(password)
                .setSalt(salt)
                .setBitState(BaseConstants.User.BIT_STATE_ENABLE)
                .setLoginId(loginUser.getId())
                .setNickName(loginUser.getUsername())
                .setPhone(userRegisterDTO.getPhone());
        // 保存用户信息
        userMapper.insert(user);
        // 保存用户详细信息
        userInfoMapper.insert(
                new UserInfo()
                        .setCreateTime(createTime)
                        .setUpdateTime(createTime)
                        .setRegTime(createTime)
                        .setLevel(1)
                        .setUserId(user.getId())
        );
    }


    private String getRedisSmsCode(String key) {
        String smsCodeByRedis = (String) redisTemplate.opsForValue().get(key);

        // 3 如果验证码已存在
        String smsCode = null;
        if (StringUtils.isNotBlank(smsCodeByRedis)) {
            smsCode = smsCodeByRedis.split(":")[0];
            String sendTime = smsCodeByRedis.split(":")[1];

            // 3.1 如果没有过重发时间,返回错误信息
            // 当前时间 - 发送时间   < 1分钟,就是没有过重发时间
            if (System.currentTimeMillis() - Long.parseLong(sendTime) < 60 * 1000) {
                throw new BusinessException(ResponseCode.RESPONSE_CODE_40019);
            }
        } else {
            // 4 如果验证码不存在,生成验证码,放入redis,并短信发送
            // 4.1 生成6位数的随机数作为短信验证码
            smsCode = StrUtils.getRandomString(6);
        }

        // 5 放入redis,并设置5分钟的过期时间和发送时间
        String value = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(key, value, 5, TimeUnit.MINUTES);
        return smsCode;
    }

    private String getMD5Password(String salt, String password) {
        return MD5.getMD5(BaseConstants.PASSWORD_ENCRYPT_PREFIX + password + salt);
    }

    private boolean equalsMD5Password(String salt, String cleartextPassword, String encryptPassword) {
        return MD5.validateMD5(BaseConstants.PASSWORD_ENCRYPT_PREFIX + cleartextPassword + salt, encryptPassword);
    }
}
